﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//Added
using System.Xml.Linq;
using System.Xml.XPath;
using System.Linq.Expressions;
using System.Text.RegularExpressions;
using System.Xml;


namespace DatabaseTestConsole
{
	static public class XpathTesting
	{
		/*
			 * 
			 * Xpath node types notes
			 * 
			 <!-- example --> @This is a comment node
			 <tns:Tutorial xmlns:tns="c#:tutorials"> @This is a Root Node
				<TutorialStep step="1">creating the if</TutorialStep>@ Element node
				<TutorialStep step="2" <-@This is attribute Node  >creating the condition</TutorialStep>
				<TutorialStep step="3">evaluating the condition <-@This is Text Node </TutorialStep>
				<TutorialStep step="4">the body</TutorialStep>
				<TutorialStep step="5">finishing up</TutorialStep>	
			 </tns:Tutorial>
			 * 
			 * 
			 * <?ship-from stock room?>@ proccesing instruction node
			 * 
			 */

		public static IEnumerable<XElement> GetElementUsingXpath(
			this XNode node,string xpath,params string[] namespaceDeclarations)
		{
			var nav = node.CreateNavigator();

			var xnm = GetXmlNamespaceManager(nav, namespaceDeclarations);

			var q = from ele in GetNodesUsingXpath(nav, xpath, xnm) select (XElement) ele;
			return q;

		}

		/*
		 * Get nodes out of the query
		 */

		private static IEnumerable<XNode>GetNodesUsingXpath(XPathNavigator nav,string xpath,
			IXmlNamespaceResolver nm)
		{
			//iterator threw nodes
			var itr = nav.Select(xpath, nm);
			//walk threw em
			while (itr.MoveNext())
			{
				// Uo=underlying object = gimme all nodes as objects
				var uo = itr.Current.UnderlyingObject;
				yield return uo as XNode;
			}

		} 

		/*
		 * Complex Regex to pull prefix and namespace off
		 */

		private static readonly Regex DeclarationPattern=
			new Regex(@"(?x:^xmlns:(?<prefix>[^:\s]+)=(?<namespace>[^\s]+)$|^(?<prefix>[^:\s]+):(?<namespace>[^\s]+)$)$",
				RegexOptions.Compiled);

		/*
		 * extension built to get namespace and prefix for xml navagator
		 * .....this better be worth it
		 */

		private static XmlNamespaceManager GetXmlNamespaceManager(XPathNavigator nav,params string[]namespaceDeclarations)
		{
			var xnm = new XmlNamespaceManager(nav.NameTable);
			if (namespaceDeclarations != null)
			{
				foreach (string namespaceDeclaration in namespaceDeclarations)
				{
					var match = DeclarationPattern.Match(namespaceDeclaration);
					if (!match.Success)
					{
						throw new ArgumentException("incorrect namespace declaration","my exception i made");
					}

					xnm.AddNamespace(match.Groups["prefix"].Value,match.Groups["namespace"].Value);
				}
			}
			if (string.IsNullOrEmpty(xnm.LookupNamespace("xhtml")))
			{
				xnm.AddNamespace("xhtml","http://www.w3.org/1999/xhtml");
			}

			return xnm;

		}

	}
}
